package lock.method;

import org.junit.jupiter.api.Test;

public class Run {

    /**
     * int getHoldCount()的作用是查询当前线程保持锁定的个数
     */
    @Test
    public void testGetHoldCount() {
        Service service = new Service();
        service.method1();
    }

    /**
     * int getQueueLength() 的作用是返回正在等待获取锁定的线程数
     * @throws InterruptedException
     */
    @Test
    public void testGetQueueLength() throws InterruptedException {
        Service2 service2 = new Service2();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(" * 线程 " + Thread.currentThread().getName() + "运行了");
                service2.method1();
            }
        };

        Thread[] threadArray = new Thread[10];
        for(int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }
        for(int i = 0; i < 10; i++) {
            threadArray[i].start();
        }

        Thread.sleep(2000);
        System.out.println(" 有" +  service2.getLock().getQueueLength());
    }

    /**
     * int getWaitQueueLength() 等待与当前锁定相关给定条件Condition的估计线程数
     */
    @Test
    public void testGetWaitQueueLength() throws InterruptedException {
        Service3 service3 = new Service3();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(" * 线程 " + Thread.currentThread().getName() + "运行了");
                service3.waitMethod();
            }
        };

        Thread[] threadArray = new Thread[10];
        for(int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }
        for(int i = 0; i < 10; i++) {
            threadArray[i].start();
        }

        Thread.sleep(2000);
        service3.notifyMethod();
    }

    /**
     * boolean hasQueueThread() 查询线程是否正在等待此锁
     * boolean hasQueueThreads() 查询是否有线程等待此锁
     */
    @Test
    public void testHasQueueThread() throws InterruptedException {
        Service4 service = new Service4();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };

        Thread threadA = new Thread(runnable);
        threadA.start();
        Thread.sleep(500);
        Thread threadB = new Thread(runnable);
        threadB.start();
        Thread.sleep(500);
        System.out.println(service.lock.hasQueuedThread(threadA));
        System.out.println(service.lock.hasQueuedThread(threadB));
        System.out.println(service.lock.hasQueuedThreads());
    }

    /**
     * 查询是否有线程正在等待与此锁定有关的condition条件
     */
    @Test
    public void testHasWaiters() throws InterruptedException {
        Service5 service = new Service5();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };

        Thread[] threadArray = new Thread[10];
        for(int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }
        for(int i = 0; i < 10; i++) {
            threadArray[i].start();
        }

        Thread.sleep(2000);
        service.notifyMethod();
    }

    /**
     * boolean isFair() 判断是否是公平锁
     * boolean isHeldByCurrentThread() 查询当前线程是否保持此锁定
     * boolean isLocked() 查询锁定是否由任意线程保持
     */
    @Test
    public void isFairAndLocked() {
        Service6 service = new Service6(true);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                service.serviceMethod();
            }
        };

        new Thread(runnable).start();
    }

    /**
     * void lockInterruptibly()的作用是：如果当前线程未被中断，则获取锁定，如果已经被中断则出现异常
     */
    @Test
    public void testLockInterruptibly() throws InterruptedException {
        MyService myService = new MyService();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                myService.waitMethod();
            }
        };

        Thread threadA = new Thread(runnable);
        threadA.setName("A");
        threadA.start();
        Thread.sleep(500);
        Thread threadB = new Thread(runnable);
        threadB.setName("B");
        threadB.start();
        threadB.interrupt();
        System.out.println("main end!");
    }

    /**
     * boolean tryLock() 的作用是，仅在调用时锁定未被另一个线程保持的情况下，才获取该锁定
     * boolean tryLock(long timeout, TimeUnit unit) 如果在指定的时间内没有被另一线程保持，且当前线程未中断，则获取该锁定
     */
    @Test
    public void testTryLock() {
        final MyService2 service = new MyService2();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };

        Thread threadA = new Thread(runnable);
        threadA.setName("A");
        threadA.start();
        Thread threadB = new Thread(runnable);
        threadB.setName("B");
        threadB.start();
    }
}
